/**
 *Copyright (c) 2024 watereyes
 * safetymanagement is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.personal.service.impl;

import com.google.gson.Gson;
import com.koron.common.bean.StaffBean;
import com.koron.common.dfs.FastDFSClientWrapper;
import com.koron.common.domain.DataBean;
import com.koron.common.generator.DefaultIdGenerator;
import com.koron.common.web.Util;

import com.koron.personal.domain.MyCertificate;
import com.koron.personal.mapper.MyCertificateMapper;
import com.koron.personal.service.api.MyCertificateService;
import com.koron.personal.utils.BusinessCode;


import com.koron.system.domain.DictData;
import com.koron.system.service.api.DictDataService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.koron.ebs.mybatis.SessionFactory;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.swan.bean.MessageBean;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Calendar;

@Service
public class MyCertificateServiceImpl implements MyCertificateService, InitializingBean {

    private final static  Logger logger = LoggerFactory.getLogger(MyCertificateServiceImpl.class);

    @Autowired
    private FastDFSClientWrapper clientWrapper;

    private static final String QUARTZ_GROUP = "myCertificate";

    // @Autowired默认按照byType 注入，也就是bean的类型的来传入,
    // 如果需要指定名字，那么需要使@Qualifier("这是bean的名字")
    @Autowired
    private Scheduler scheduler;

    @Autowired
    private Util util;

    @Autowired
    private DictDataService dataService;

    @Override
    public MessageBean<Integer> save(MyCertificate bean, String keepFiles, String delFies, MultipartFile[] files) {
        MessageBean<Integer> msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), "保存成功", Integer.class);
        List<String> keepList = new ArrayList<>();
        try (SessionFactory factory = new SessionFactory()) {
            if (StringUtils.isEmpty(bean.getCertificateName())) {
                msg.setCode(BusinessCode.CERTIFICATE_EMPTY_NAME.getCode());
                msg.setDescription(BusinessCode.CERTIFICATE_EMPTY_NAME.getDescription());
                return msg;
            }
            if (null == bean.getPeriod()) {
                msg.setCode(BusinessCode.CERTIFICATE_EMPTY_PERIOD.getCode());
                msg.setDescription(BusinessCode.CERTIFICATE_EMPTY_PERIOD.getDescription());
                return msg;
            }
            if (null != files && files.length > 0) {
                for (MultipartFile file : files) {
                    String url = clientWrapper.uploadFile(file);
                    keepList.add(url + "#" + file.getOriginalFilename());
                }
            }
            if (StringUtils.isNotEmpty(bean.getJobsStaffCertificateId())) {
                MyCertificate entity = factory.getMapper(MyCertificateMapper.class).queryByStaffCodeAndJobsStaffCertificateId(
                        bean.getStaffCode(), bean.getJobsStaffCertificateId(), bean.getId());
                if (null != entity) {
                    msg.setCode(BusinessCode.CERTIFICATE_IS_EXISTED.getCode());
                    msg.setDescription(BusinessCode.CERTIFICATE_IS_EXISTED.getDescription());
                    return msg;
                }
            }
            Integer value = 0;
            if (StringUtils.isEmpty(bean.getId())) {
                //新增
                bean.setId(DefaultIdGenerator.getInstance().generateLongId());
                bean.setAddTime(new Date());
                if (null == keepList || keepList.size() <= 0) {
                    msg.setCode(BusinessCode.CERTIFICATE_EMPTY_ATTACHMENT.getCode());
                    msg.setDescription(BusinessCode.CERTIFICATE_EMPTY_ATTACHMENT.getDescription());
                    return msg;
                }
                bean.setAttachment(new Gson().toJson(keepList));
                value = factory.getMapper(MyCertificateMapper.class).insert(bean);
                excuteJob(bean);
            } else {
                //修改
                MyCertificate entity = queryOne(bean.getId()).getData();
                if (null == entity) {
                    msg.setCode(BusinessCode.CERTIFICATE_NOT_EXIST.getCode());
                    msg.setDescription(BusinessCode.CERTIFICATE_NOT_EXIST.getDescription());
                    return msg;
                }
                bean.setAddTime(new Date());
                if (StringUtils.isNotEmpty(keepFiles)) {
                    String[] keepArray = keepFiles.split("[,，]");
                    keepList.addAll(Arrays.asList(keepArray));
                }
                bean.setAttachment(new Gson().toJson(keepList));
                value = factory.getMapper(MyCertificateMapper.class).update(bean);
                if (value > 0) {
                    if (StringUtils.isNotEmpty(delFies)) {
                        String[] delArray = delFies.split("[,，]");
                        for (String delUrl : delArray) {
                            clientWrapper.deleteFile(delUrl.split("#")[0]);
                        }
                    }
                }
            }
            msg.setData(value);
            if (value < 0) {
                if (null != keepList && keepList.size() > 0) {
                    if (StringUtils.isEmpty(keepFiles)) {
                        for (String url : keepList) {
                            clientWrapper.deleteFile(url.split("#")[0]);
                        }
                    } else {
                        List<String> keeps = Arrays.asList(keepFiles.split("[,，]"));
                        for (String url : keepList) {
                            if (!keeps.contains(url)) {
                                clientWrapper.deleteFile(url.split("#")[0]);
                            }
                        }
                    }
                }
                msg.setCode(BusinessCode.SUCCESS.getCode());
                msg.setDescription("保存失败");
            }
            return msg;
        } catch (Exception e) {
            if (null != keepList && keepList.size() > 0) {
                if (StringUtils.isEmpty(keepFiles)) {
                    for (String url : keepList) {
                        clientWrapper.deleteFile(url.split("#")[0]);
                    }
                } else {
                    List<String> keeps = Arrays.asList(keepFiles.split("[,，]"));
                    for (String url : keepList) {
                        if (!keeps.contains(url)) {
                            clientWrapper.deleteFile(url.split("#")[0]);
                        }
                    }
                }
            }
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            return msg;
        }
    }

    @Override
    public MessageBean<Integer> delete(String id) {
        MessageBean<Integer> msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), "删除成功", Integer.class);
        try (SessionFactory factory = new SessionFactory()) {
            if (StringUtils.isEmpty(id)) {
                msg.setDescription(BusinessCode.NOT_CHANGE_DATA.getDescription());
                msg.setCode(BusinessCode.NOT_CHANGE_DATA.getCode());
                return msg;
            }
            MyCertificate entity = queryOne(id).getData();
            if (null == entity) {
                msg.setCode(BusinessCode.CERTIFICATE_NOT_EXIST.getCode());
                msg.setDescription(BusinessCode.CERTIFICATE_NOT_EXIST.getDescription());
                return msg;
            }
            Integer value = factory.getMapper(MyCertificateMapper.class).delete(id);
            msg.setData(value);
            if (value <= 0) {
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription("删除失败");
                return msg;
            }
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            return msg;
        }
    }

    @Override
    public MessageBean<MyCertificate> queryOne(String id) {
        MessageBean<MyCertificate> msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), "查询证照详情成功", MyCertificate.class);
        try (SessionFactory factory = new SessionFactory()) {
            if (StringUtils.isNotEmpty(id)) {
                MyCertificate entity = factory.getMapper(MyCertificateMapper.class).queryOne(id);
                msg.setData(entity);
            }
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            return msg;
        }
    }

    @Override
    public MessageBean<DataBean<MyCertificate>> list(String staffCode, Integer start, Integer rows, String keyword) {
        MessageBean<DataBean<MyCertificate>> msg = new MessageBean<>();
        try (SessionFactory factory = new SessionFactory()) {
            List<MyCertificate> list = factory.getMapper(MyCertificateMapper.class).queryByCondition(staffCode, start, rows,keyword);
            Integer totalNumber = factory.getMapper(MyCertificateMapper.class).countByCondition(staffCode,keyword);
            rows = rows == null ? totalNumber : (rows <= 0 ? 1 : rows);
            Integer totalPage = (totalNumber > rows) ? (totalNumber % rows == 0 ? totalNumber / rows : totalNumber / rows + 1) : 1;
            DataBean<MyCertificate> dataBean = new DataBean<>();
            dataBean.setList(list);
            dataBean.setTotalNumber(totalNumber);
            dataBean.setTotalPage(totalPage);
            dataBean.setPageSize(rows);
            msg.setCode(com.koron.accident.util.BusinessCode.SUCCESS.getCode());
            msg.setDescription("获取我的证照列表成功");
            msg.setData(dataBean);
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setDescription(com.koron.accident.util.BusinessCode.EXCEPTION.getDescription());
            msg.setCode(com.koron.accident.util.BusinessCode.EXCEPTION.getCode());
            return msg;
        }
    }

    @Override
    public MessageBean<?> queryRequiredCertificate(String userCode) {
        MessageBean<List> msg = new MessageBean<>();
        try (SessionFactory factory = new SessionFactory()) {
            List<Map<String, Object>> list = factory.getMapper(MyCertificateMapper.class).queryRequiredCertificate(userCode);
            msg.setCode(com.koron.accident.util.BusinessCode.SUCCESS.getCode());
            msg.setDescription("获取证照列表成功");
            msg.setData(list);
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setDescription(com.koron.accident.util.BusinessCode.EXCEPTION.getDescription());
            msg.setCode(com.koron.accident.util.BusinessCode.EXCEPTION.getCode());
            return msg;
        }
    }

    @Override
    public MessageBean<?> queryDuties(String userCode) {
        MessageBean<List> msg = new MessageBean<>();
        try (SessionFactory factory = new SessionFactory()) {
            List<Map<String, Object>> list = factory.getMapper(MyCertificateMapper.class).queryDuties(userCode);
            List<Map<String, String>> maps = new ArrayList<Map<String, String>>();
            if (null != list && list.size() > 0) {
                String dutiesId = (String) list.get(0).get("jobsId");
                String dutiesName = (String) list.get(0).get("jobsName");
                String[] dutiesArray = dutiesId.split("[,，;；]");
                String[] dutiesNameArray = dutiesName.split("[,，;；]");
                for (int i = 0; i < dutiesArray.length; i++) {
                    Map<String, String> map1 = new HashMap<>();
                    map1.put("dutiesId", dutiesArray[i]);
                    map1.put("dutiesName", dutiesNameArray[i]);
                    maps.add(map1);
                }
            }
            msg.setCode(com.koron.accident.util.BusinessCode.SUCCESS.getCode());
            msg.setDescription("获取职责列表成功");
            msg.setData(maps);
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setDescription(com.koron.accident.util.BusinessCode.EXCEPTION.getDescription());
            msg.setCode(com.koron.accident.util.BusinessCode.EXCEPTION.getCode());
            return msg;
        }
    }

    @Override
    public MessageBean<Boolean> importFromExcel(StaffBean user, MultipartFile file, String corpCode) throws Exception {
        MessageBean<Boolean> msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), Boolean.class);
        SessionFactory factory = null;
        try {
            factory = new SessionFactory();
            if (null == file) {
                msg.setCode(BusinessCode.NOT_CHANGE_DATA.getCode());
                msg.setDescription("未选中文件");
                return msg;
            }
            InputStream inputStream = file.getInputStream();
            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            if (null == workbook) {
                logger.error("上传文件为空");
                msg.setCode(BusinessCode.NOT_CHANGE_DATA.getCode());
                msg.setDescription("上传文件为空");
                return msg;
            }
            XSSFSheet sheet = workbook.getSheetAt(0);
            if (sheet == null) {
                logger.error("上传文件为空");
                msg.setCode(BusinessCode.NOT_CHANGE_DATA.getCode());
                msg.setDescription("上传文件为空");
                return msg;
            }
            List<MyCertificate> insertMyCertificateList = new ArrayList<>();
            List<MyCertificate> updateMyCertificateList = new ArrayList<>();
            for (int rowNum = 2; rowNum <= sheet.getLastRowNum(); rowNum++) {
                Row row = sheet.getRow(rowNum);
                if (null != row) {
                    String userId = getCellValue(row.getCell(0));
                    String certificateTypeName = getCellValue(row.getCell(1));
                    String certificateCode = getCellValue(row.getCell(2));
                    String periodString = getCellValue(row.getCell(3));
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    Date period = sdf.parse(periodString);
                    setMyCertificate(factory, user, insertMyCertificateList, updateMyCertificateList, userId, certificateTypeName, certificateCode, corpCode, period);
                }
            }
            if (null != insertMyCertificateList && insertMyCertificateList.size() > 0) {
                factory.getMapper(MyCertificateMapper.class).batchInsert(insertMyCertificateList);
            }
            if (null != updateMyCertificateList && updateMyCertificateList.size() > 0) {
                factory.getMapper(MyCertificateMapper.class).batchUpdate(updateMyCertificateList);
            }
            factory.close();
            msg.setDescription("上传成功");
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            if (null != factory)
                factory.close(false);
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            return msg;
        }finally {
            if (null != factory){
                factory.close();
            }
        }
    }

    public String getCellValue(Cell cell) {
        if (cell == null)
            return "";
        if (cell.getCellTypeEnum() == CellType.STRING) {
            return cell.getStringCellValue();
        } else if (cell.getCellTypeEnum() == CellType.BOOLEAN) {
            return String.valueOf(cell.getBooleanCellValue());
        } else if (cell.getCellTypeEnum() == CellType.FORMULA) {
            return cell.getCellFormula();
        } else if (cell.getCellTypeEnum() == CellType.NUMERIC) {
            return String.valueOf(cell.getNumericCellValue());
        } else {
            return "";
        }
    }

    private void setMyCertificate(SessionFactory factory, StaffBean user, List<MyCertificate> insertMyCertificateList, List<MyCertificate> updateMyCertificateList, String userId,
                                  String certificateTypeName, String certificateCode, String corpCode, Date period) throws Exception {
        //根据userId获取用户信息
        List<StaffBean> staffBeanList = (List<StaffBean>) util.staff(userId, 2).getData();
        if (null == staffBeanList || staffBeanList.size() <= 0) {
            return;
        }
        DictData dictData = dataService.matchDictData("证照类型", certificateTypeName);
        if (null == dictData) {
            return;
        }
        String staffCode = staffBeanList.get(0).getCode();
        String certificateTypeId = dictData.getId();
        Date date = new Date();
        //根据用户code和证照类型id去查询有多少个同一个用户下有多少个同一个类型的证件
//        List<JobsStaffCertificate> jobsStaffCertificateList=factory.getMapper(JobsStaffCertificateMapper.class).queryByUserCodeAndTypeId(staffCode,certificateTypeId);
//        if (null!=jobsStaffCertificateList&&jobsStaffCertificateList.size()>0){
//            for(JobsStaffCertificate jobsStaffCertificate:jobsStaffCertificateList){
//                //根据职位id获取职位信息
//                MyCertificate certificate=new MyCertificate();
//                if (StringUtils.isNotEmpty(jobsStaffCertificate.getDutiesId())){
//                    JobsDuties jobsDuties=factory.getMapper(JobsDutiesMapper.class).queryById(jobsStaffCertificate.getDutiesId());
//                    if(null!=jobsDuties){
//                        certificate.setDutiesName(jobsDuties.getName());
//                        certificate.setDutiesId(jobsStaffCertificate.getDutiesId());
//                    }
//                }
//                certificate.setAddTime(date);
//                certificate.setCertificateType(certificateTypeId);
//                certificate.setStaffCode(staffCode);
//                certificate.setStaffName(staffBeanList.get(0).getName());
//                certificate.setType(0);
//                certificate.setPeriod(period);
//                certificate.setCorpCode(corpCode);
//                certificate.setCertificateCode(certificateCode);
//                certificate.setDeptCode(staffBeanList.get(0).getDepartmentCode());
//                certificate.setJobsStaffCertificateId(jobsStaffCertificate.getId());
//                certificate.setCertificateName(jobsStaffCertificate.getCertificateTypeLabel());
//                //判断该用户是否已经导入过该类型的证件
//                MyCertificate checkExist=factory.getMapper(MyCertificateMapper.class).queryByStaffCodeAndJobsStaffCertificateId(staffCode,jobsStaffCertificate.getId(),null);
//                if (null==checkExist){
//                    certificate.setId(DefaultIdGenerator.getInstance().generateLongId());
//                    insertMyCertificateList.add(certificate);
//                }else{
//                    certificate.setId(checkExist.getId());
//                    updateMyCertificateList.add(certificate);
//                }
//            }
//        }else{
//
//        }
        MyCertificate certificate = new MyCertificate();
        certificate.setAddTime(date);
        certificate.setCertificateType(certificateTypeId);
        certificate.setStaffCode(staffCode);
        certificate.setStaffName(staffBeanList.get(0).getName());
        certificate.setType(0);
        certificate.setPeriod(period);
        certificate.setCorpCode(corpCode);
        certificate.setCertificateCode(certificateCode);
        certificate.setDeptCode(staffBeanList.get(0).getDepartmentCode());
        certificate.setCertificateName(dictData.getDictLabel());
        //判断该用户是否已经导入过该类型的证件
        List<MyCertificate> checkExist = factory.getMapper(MyCertificateMapper.class).queryByStaffCodeAndCertificateType(staffCode, dictData.getId(), null);
        if (null == checkExist && checkExist.size() <= 0) {
            certificate.setId(DefaultIdGenerator.getInstance().generateLongId());
            insertMyCertificateList.add(certificate);
        } else {
            certificate.setId(checkExist.get(0).getId());
            updateMyCertificateList.add(certificate);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        scheduler.start();
        try (SessionFactory factory = new SessionFactory()) {
            Date date = new Date();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DAY_OF_MONTH, 7);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            Date time = calendar.getTime();
            //提前7天通知
            List<MyCertificate> list = factory.getMapper(MyCertificateMapper.class).queryByCondition(null, null, null,null);
            if (null != list && list.size() > 0) {
                for (MyCertificate certificate : list) {
                    excuteJob(certificate);
                }
            }
        }
    }

    private void excuteJob(MyCertificate myCertificate) {
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, 7);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date time = calendar.getTime();
        try {
            if (getBeginTime(myCertificate.getPeriod()).compareTo(time) == 0) {
                CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder
                        .cronSchedule("0 0 0 * * ?");
                JobDetail job = JobBuilder.newJob(MyCertificateJob.class).withIdentity(myCertificate.getId(), QUARTZ_GROUP)
                        .usingJobData("id", myCertificate.getId()).build();
                Trigger trigger = TriggerBuilder.newTrigger()
                        .withIdentity(myCertificate.getId(), QUARTZ_GROUP).withSchedule(cronScheduleBuilder).build();
                // Tell quartz to schedule the job using our trigger
                scheduler.scheduleJob(job, trigger);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }
    }

    private Date getBeginTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, 3);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
}
